package ru.efko.dims.activity;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import ru.efko.dims.R;
import ru.efko.dims.domain.SensorDevice;
import ru.efko.dims.domain.SensorDeviceImpl;
import ru.efko.dims.util.ThreadLocalVariablesKeeper;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Pair;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;

public class SettingsActivity extends Activity {

	private SeekBar vrfSeekBar;
	private SeekBar cmvSeekBar;
	private SeekBar roughSeekBar;
	private SeekBar fromSeekBar;
	private SeekBar vpullSeekBar;
	private SeekBar acoSeekBar;
	private SeekBar accurateSeekBar;
	private SeekBar toSeekBar;

	private EditText vrfEditText;
	private EditText cmvEditText;
	private EditText roughEditText;
	private EditText fromEditText;
	private EditText vpullEditText;
	private EditText acoEditText;
	private EditText accurateEditText;
	private EditText toEditText;

	private CheckBox manualFlag;
	private CheckBox zoomFlag;
	private CheckBox winFlag;
	private CheckBox vpullFlag;
	private CheckBox vrfFlag;
	private CheckBox bit2Flag;
	private CheckBox bit1Flag;
	private CheckBox bit0Flag;

	private final static int SETTINGS_NUMBER = 8;

	private ArrayList<SeekBar> seekBarSet = new ArrayList<SeekBar>(
			SETTINGS_NUMBER);
	private ArrayList<EditText> editTextSet = new ArrayList<EditText>(
			SETTINGS_NUMBER);
	private ArrayList<CheckBox> checkBoxSet = new ArrayList<CheckBox>(
			SETTINGS_NUMBER);
	private static final List<Pair<Integer, Integer>> USER_RANGE_VALUES = new LinkedList<Pair<Integer, Integer>>() {
		private static final long serialVersionUID = 3929048652602726625L;

		{
			add(new Pair<Integer, Integer>(6, 27));
			add(new Pair<Integer, Integer>(0, 150));
			add(new Pair<Integer, Integer>(0, 1));
			add(new Pair<Integer, Integer>(1, 500));
			add(new Pair<Integer, Integer>(240, 705));
			add(new Pair<Integer, Integer>(0, 15));
			add(new Pair<Integer, Integer>(-84, 84));
			add(new Pair<Integer, Integer>(-84, 84));
		}
	};

	private static final List<Pair<Integer, Integer>> REAL_RANGE_VALUES = new LinkedList<Pair<Integer, Integer>>() {
		{
			add(new Pair<Integer, Integer>(1246, 5400));
			add(new Pair<Integer, Integer>(0, 2300));
			add(new Pair<Integer, Integer>(0, 1));
			add(new Pair<Integer, Integer>(1, 500));
			add(new Pair<Integer, Integer>(256, 752));
			add(new Pair<Integer, Integer>(0, 32767));
			add(new Pair<Integer, Integer>(0, 2048));
			add(new Pair<Integer, Integer>(0, 2048));
		}

	};

	private static final int MENU_SETTINGS = 1;
	private static final int MENU_DISCONNECT = 2;
	private SensorDevice sensorDevice = new SensorDeviceImpl();

	// TODO set from settings

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_settings);
		init();
		sensorDevice = ThreadLocalVariablesKeeper.getSensorDevice();
		setCommandValues();
		addBarsListeners();

	}

	private void init() {
		vrfSeekBar = SeekBar.class.cast(findViewById(R.id.vrfVSeekBar));
		seekBarSet.add(vrfSeekBar);
		vrfEditText = EditText.class.cast(findViewById(R.id.vrfVEditText));
		editTextSet.add(vrfEditText);

		vpullSeekBar = SeekBar.class.cast(findViewById(R.id.vpullSeekBar));
		seekBarSet.add(vpullSeekBar);
		vpullEditText = EditText.class.cast(findViewById(R.id.vpullEditText));
		editTextSet.add(vpullEditText);

		cmvSeekBar = SeekBar.class.cast(findViewById(R.id.cmVVSeekBar));
		seekBarSet.add(cmvSeekBar);
		cmvEditText = EditText.class.cast(findViewById(R.id.cmVVEditText));
		editTextSet.add(cmvEditText);

		acoSeekBar = SeekBar.class.cast(findViewById(R.id.acoSeekBar));
		seekBarSet.add(acoSeekBar);
		acoEditText = EditText.class.cast(findViewById(R.id.acoEditText));
		editTextSet.add(acoEditText);

		roughSeekBar = SeekBar.class.cast(findViewById(R.id.roughSeekBar));
		seekBarSet.add(roughSeekBar);
		roughEditText = EditText.class.cast(findViewById(R.id.roughEditText));
		editTextSet.add(roughEditText);

		accurateSeekBar = SeekBar.class
				.cast(findViewById(R.id.accurateSeekBar));
		seekBarSet.add(accurateSeekBar);
		accurateEditText = EditText.class
				.cast(findViewById(R.id.accurateEditText));
		editTextSet.add(accurateEditText);

		fromSeekBar = SeekBar.class.cast(findViewById(R.id.fromVSeekBar));
		seekBarSet.add(fromSeekBar);
		fromEditText = EditText.class.cast(findViewById(R.id.fromVEditText));
		editTextSet.add(fromEditText);

		toSeekBar = SeekBar.class.cast(findViewById(R.id.toSeekBar));
		seekBarSet.add(toSeekBar);
		toEditText = EditText.class.cast(findViewById(R.id.toEditText));
		editTextSet.add(toEditText);

		manualFlag = CheckBox.class.cast(findViewById(R.id.fManualCheckBox));
		checkBoxSet.add(manualFlag);

		zoomFlag = CheckBox.class.cast(findViewById(R.id.fZoomCheckBox));
		checkBoxSet.add(zoomFlag);

		winFlag = CheckBox.class.cast(findViewById(R.id.fWinCheckBox));
		checkBoxSet.add(winFlag);

		vpullFlag = CheckBox.class.cast(findViewById(R.id.fVpullCheckBox));
		checkBoxSet.add(vpullFlag);

		vrfFlag = CheckBox.class.cast(findViewById(R.id.fVRFCheckBox));
		checkBoxSet.add(vrfFlag);

		bit2Flag = CheckBox.class.cast(findViewById(R.id.fBit2CheckBox));
		checkBoxSet.add(bit2Flag);

		bit1Flag = CheckBox.class.cast(findViewById(R.id.fBit1CheckBox));
		checkBoxSet.add(bit1Flag);

		bit0Flag = CheckBox.class.cast(findViewById(R.id.fBit0CheckBox));
		checkBoxSet.add(bit0Flag);

	}

	private void setCommandValues() {
		int[] params = sensorDevice.get_parameters();
		int i = 0;
		Iterator<EditText> associated = editTextSet.iterator();
		Iterator<Pair<Integer, Integer>> userPairIterator = USER_RANGE_VALUES.iterator();
		Iterator<Pair<Integer, Integer>> realPairIterator = REAL_RANGE_VALUES.iterator();
		for (SeekBar current : seekBarSet) {
			final Pair<Integer, Integer> userRange = userPairIterator.next();
			final Pair<Integer, Integer> range = realPairIterator.next();
			Integer value = userRange.first + params[i] * (userRange.second - userRange.first)
					/ (range.second - range.first);
			current.setProgress(value);
			associated.next().setText(String.valueOf(params[i]));
			i++;
		}

		for (CheckBox current : checkBoxSet) {
			int value = (params[9] >> i) & 0x01;
			current.setChecked(value == 1);
		}

	}

	private void addBarsListeners() {
		Iterator<EditText> etIterator = editTextSet.iterator();
		Iterator<SeekBar> sbIterator = seekBarSet.iterator();
		Iterator<Pair<Integer, Integer>> userPairIterator = USER_RANGE_VALUES.iterator();
		Iterator<Pair<Integer, Integer>> realPairIterator = REAL_RANGE_VALUES.iterator();
		int i = 0;
		while (sbIterator.hasNext()) {
			final int currentNum = i;
			final SeekBar current = sbIterator.next();
			final EditText associated = etIterator.next();
			final Pair<Integer, Integer> range = userPairIterator.next();
			final Pair<Integer, Integer> realRange = realPairIterator.next();

			current.setMax(range.second - range.first);
			current.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

				@Override
				public void onStopTrackingTouch(SeekBar seekBar) {
					// TODO Auto-generated method stub

				}

				@Override
				public void onStartTrackingTouch(SeekBar seekBar) {
					// TODO Auto-generated method stub

				}

				@Override
				public void onProgressChanged(SeekBar seekBar, int progress,
						boolean fromUser) {
					String value = String.valueOf(current.getProgress());
					associated.setText(String.valueOf(Integer.parseInt(value) + range.first));

				}
			});

			associated.addTextChangedListener(new TextWatcher() {

				@Override
				public void onTextChanged(CharSequence s, int start,
						int before, int count) {
					Integer value = s.length() == 0 ? range.first : Integer
							.parseInt(s.toString());
					if (value < range.first) {
						value = range.first;
						associated.setText(String.valueOf(value));
					}
					if (value > range.second) {
						value = range.second;
						associated.setText(String.valueOf(value));
					}
					int[] paramsToSend = sensorDevice.get_parameters();
					paramsToSend[currentNum] = realRange.first + value * (realRange.second - realRange.first)
							/ (range.second - range.first);
					sensorDevice.set_parameters(paramsToSend);
					current.setProgress(value - range.first);

				}

				@Override
				public void beforeTextChanged(CharSequence s, int start,
						int count, int after) {
					// TODO Auto-generated method stub

				}

				@Override
				public void afterTextChanged(Editable s) {
					// TODO Auto-generated method stub

				}
			});
			i++;
		}

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		menu.add(Menu.NONE, MENU_SETTINGS, 0, R.string.menu_graphics).setIcon(
				android.R.drawable.ic_menu_info_details);
		menu.add(Menu.NONE, MENU_DISCONNECT, 1, R.string.menu_disconnect);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle item selection
		switch (item.getItemId()) {
		case MENU_SETTINGS:
			Intent graphicsIntent = new Intent(SettingsActivity.this,
					GraphicsActivity.class);
			SettingsActivity.this.startActivity(graphicsIntent);
			return true;
		case MENU_DISCONNECT:
			sensorDevice.disconnect();
			ThreadLocalVariablesKeeper.clean();
			Intent startIntent = new Intent(SettingsActivity.this,
					StartActivity.class);
			SettingsActivity.this.startActivity(startIntent);
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		return super.onKeyDown(keyCode, event);
	}

}
